package com.algo.linkedList;

import com.sun.xml.internal.ws.addressing.model.InvalidAddressingHeaderException;
import jdk.nashorn.internal.ir.ReturnNode;
import org.junit.Test;

import java.util.LinkedList;
import java.util.Scanner;


public class LRUBaseLinkedList<T> {


    //默认链表容量
    private final static Integer DEFAULT_CAPACITY = 10;

    private SNode<T> headNode;

    //链表长度
    private Integer length;

    private Integer capacity;

    public LRUBaseLinkedList(Integer capacity) {
        this.headNode = new SNode<>();
        this.capacity = capacity;
        this.length = 0;
    }

    public LRUBaseLinkedList() {
        this(DEFAULT_CAPACITY);
    }

    public void offer(T object) {
        if (object == null) {
            throw new IllegalArgumentException("该缓存容器不支持null");
        }
        SNode lastNode = findLastNode(object);
        if (lastNode != null) {
            updateNode(lastNode, object);
        } else {
            if (this.length < this.capacity) {
                addHead(object);
            } else {
                removeEnd();
                addHead(object);
            }
        }

    }

    public void printNode() {
        SNode<T> node = headNode.next;
        StringBuilder sb = new StringBuilder();
        while (node != null) {
            sb.append(node.getValue() + ",");
            node = node.next;
        }
        sb.setLength(sb.length() - 1);
        System.out.println(sb.toString());
    }

    private void updateNode(SNode lastNode, T object) {
        lastNode.next = lastNode.next.next;

        this.length--;
        addHead(object);
    }

    private void removeEnd() {
        SNode<T> temp = this.headNode;
        while (temp.next != null) {
            if (temp.next.next == null) {
                temp.next = null;
                break;
            }
            temp = temp.next;
        }
        this.length--;

    }

    private void addHead(T object) {
        SNode<T> node = new SNode<>(object);
        node.next = this.headNode.next;
        this.headNode.next = node;
        this.length++;
    }

    public SNode findLastNode(T object) {
        SNode<T> temp = this.headNode.next;
        SNode<T> result = this.headNode;
        while (temp != null) {
            if (temp.value == object) {
                return result;
            }
            result = temp;
            temp = temp.next;
        }
        return null;
    }


    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        LRUBaseLinkedList<Integer> list = new LRUBaseLinkedList<>();
        while (true) {
            list.offer(sc.nextInt());
            list.printNode();
        }
    }


    public class SNode<T> {

        private SNode next;

        private T value;

        public SNode() {
        }

        public SNode(T value) {

            this.value = value;
        }

        public SNode(SNode next, T value) {
            this.next = next;
            this.value = value;
        }

        public SNode getNext() {
            return next;
        }

        public void setNext(SNode next) {
            this.next = next;
        }

        public T getValue() {
            return value;
        }

        public void setValue(T value) {
            this.value = value;
        }
    }
}
